# -*- coding: utf-8 -*-

try:
    import configparser
except Exception:
    import ConfigParser as configparser

import os
import stat
import br.utils
import json
import br.vars
import br.configuration
import br.log

VULNERABILITY_INI_FILEPATH = br.vars.SSR_BR_PLUGIN_PYTHON_ROOT_DIR + \
    "/br/config/vulnerability-scan.ini"
INVALID_RPMS_KEY = "invalid_rpms"
FILE_GROUP_VULNERABILITY = "Vulnerability"
# FPK: File vulnerability Key
FPK_MODE_FILE_LIST = "PackageList"

if len(br.utils.subprocess_has_output("cat  /etc/.kyinfo  | grep 'milestone = 3.2'")) != 0:
    OPENSSH_CHECK_VERSION = "9.3p2-2"
    OPENSSL_CHECK_VERSION = "1.1.1p-60"
    SUDO_CHECK_VERSION = "1.8.6p3-28"
    POLKIT_CHECK_VERSION = "0.96-11"
    NTP_CHECK_VERSION = "4.2.8p14-12"
    BASH_CHECK_VERSION = "4.4.30-80"
elif len(br.utils.subprocess_has_output("cat  /etc/.kyinfo  | grep 'milestone = 3.3'")) != 0:
    OPENSSH_CHECK_VERSION = "9.3p2-1"
    OPENSSL_CHECK_VERSION = "1.1.1t-60"
    SUDO_CHECK_VERSION = "1.9.5p2-3"
    POLKIT_CHECK_VERSION = "0.112-26"
    NTP_CHECK_VERSION = "4.2.8p14-28"
    BASH_CHECK_VERSION = ""
elif len(br.utils.subprocess_has_output("cat  /etc/.kyinfo  | grep 'milestone = 3.4'")) != 0:
    OPENSSH_CHECK_VERSION = "9.2p1-1"
    OPENSSL_CHECK_VERSION = "1.1.1u-22"
    SUDO_CHECK_VERSION = ""
    POLKIT_CHECK_VERSION = "0.115-11"
    NTP_CHECK_VERSION = ""
    BASH_CHECK_VERSION = ""
else:
    POLKIT_CHECK_VERSION = ""
    BASH_CHECK_VERSION = ""
    SUDO_CHECK_VERSION = ""
    POLKIT_CHECK_VERSION = ""
    NTP_CHECK_VERSION = ""
    BASH_CHECK_VERSION = ""


CHECK_RPM_VERSION_CMD = 'function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }'
CUT_RPM_VERSION_CMD = 'rpm -q --qf "%{Version}\n"'
CUT_RPM_RELEASE_CMD = 'rpm -q --qf "%{Release}\n"'
AWK_RPM_RELEASE_CMD = "| awk '{split($1, arr, \".\"); print arr[1]}'"


class VulnerabilityScan:
    def __init__(self):
        self.conf = configparser.ConfigParser()
        self.conf.read(VULNERABILITY_INI_FILEPATH)
        self.rpm_version = ""
        self.rpm_release = ""
        self.is_scan = False
        try:
            self.mode_filelist = self.conf.get(
                FILE_GROUP_VULNERABILITY, FPK_MODE_FILE_LIST).split(';')
        except Exception as e:
            self.mode_filelist = list()
            br.log.debug(str(e))

    def check_package_version(self, package_name):
        br.log.debug("check rpm version : ")
        result = 0
        if len(br.utils.subprocess_has_output("rpm -qa {0}".format(package_name))) == 0:
            return result
        self.rpm_version = str(br.utils.subprocess_has_output(
            '{0} {1}'.format(CUT_RPM_VERSION_CMD, package_name)))
        self.rpm_release = str(br.utils.subprocess_has_output(
            "{0} {1} {2}".format(CUT_RPM_RELEASE_CMD, package_name, AWK_RPM_RELEASE_CMD)))
        check_shell_def = ";  if version_ge"
        check_shell_tail = "; then echo 1; else echo -1; fi"
        check_cmd = CHECK_RPM_VERSION_CMD + " " + check_shell_def + " " + self.rpm_version + "-" + self.rpm_release
        if package_name == "openssh" and OPENSSH_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + OPENSSH_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(OPENSSH_CHECK_VERSION))
        elif package_name == "openssl" and OPENSSL_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + OPENSSL_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(OPENSSL_CHECK_VERSION))
        elif package_name == "sudo" and SUDO_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + SUDO_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(SUDO_CHECK_VERSION))
        elif package_name == "ntp" and NTP_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + NTP_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(NTP_CHECK_VERSION))
        elif package_name == "bash" and BASH_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + BASH_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(BASH_CHECK_VERSION))
        elif package_name == "polkit" and POLKIT_CHECK_VERSION != "":
            result = int(br.utils.subprocess_has_output(check_cmd + " " + POLKIT_CHECK_VERSION + " " + check_shell_tail))
            br.log.debug(str(POLKIT_CHECK_VERSION))

        return result

    def get(self):
        retdata = dict()
        retdata["enabled"] = False

        # 文件扫描返回结果给前台
        invalid_rpms = ""

        if self.is_scan:
            for mode_file in self.mode_filelist:
                br.log.debug(str(mode_file))
                if int(self.check_package_version(mode_file)) >= 0:
                    continue
                else:
                    invalid_rpms += mode_file + " " + self.rpm_version + "-" + self.rpm_release + ";"

        br.log.debug(str(invalid_rpms))
        if invalid_rpms == "":
            retdata[INVALID_RPMS_KEY] = ";"
        else:
            retdata[INVALID_RPMS_KEY] = invalid_rpms

        return (True, json.dumps(retdata))

    def set(self, args_json):
        args = json.loads(args_json)

        if args["enabled"]:
            self.is_scan = True
        else:
            self.is_scan = False

        return (True, '')
